import tkinter as tk
import tkinter.colorchooser as tkcc
import turtle as p
import time
import threading

window = tk.Tk()
window.title('金蛋蛋的Turtle Helper')
entryVar = tk.IntVar(window)
entry1 = tk.Entry(window,textvariable=entryVar,width=4,font=('Arial', 15))
entry1.grid(row=1,column=1)
entryVar.set(100)
p.delay(25)

pd = True
fill = False
color = '#000000'
p.color(color,color)

class Stack:
    def __init__(self):
        self.__list = []
    def is_empty(self):
        return self.__list == []
    def push(self,item):
        self.__list.append(item)
    def pop(self):
        if self.is_empty():
            return 
        else:
            return self.__list.pop()
    def top(self): 
        if self.is_empty():
            return
        else:
            return self.__list[-1]

def reverse(cmd):
    if cmd=='handler.fd':
        return 'handler.bk'
    elif cmd=='handler.bk':
        return 'handler.fd'
    elif cmd=='handler.lt':
        return 'handler.rt'
    elif cmd=='handler.rt':
        return 'handler.lt'

def btnDis():
    global btn1
    global btn2
    global btn3
    global btn4
    global btn5
    global btn6
    global btnUndo
    global btnRedo
    btn1['state']=btn2['state']=btn3['state']=btn4['state']=btn5['state']=btn6['state']=btnUndo['state']=btnRedo['state']=tk.DISABLED
def btnEna():
    global btn1
    global btn2
    global btn3
    global btn4
    global btn5
    global btn6
    global btnUndo
    global btnRedo
    btn1['state']=btn2['state']=btn3['state']=btn4['state']=btn5['state']=btn6['state']=btnUndo['state']=btnRedo['state']=tk.ACTIVE

class UndoRedo:
    def __init__(self):
        self.__stackUndo = Stack()
        self.__stackRedo = Stack()
    def clearRedo(self):
        self.__stackRedo = Stack()
        global btnRedo
        btnRedo['state'] = tk.DISABLED
    def recordUndo(self,cmd,entry):
        self.__stackUndo.push({'cmd':cmd,'entry':entry})
        global btnUndo
        btnUndo['state'] = tk.ACTIVE
    def undo(self):
        global btnUndo
        global btnRedo
        if self.__stackUndo.is_empty():
            return
        else:
            entryVar.set(self.__stackUndo.top()['entry'])
            btnDis()
            p.pencolor('white')
            exec('r'+reverse(self.__stackUndo.top()['cmd'])+'()')
            btnEna()
            p.pencolor(color)
            self.__stackRedo.push(self.__stackUndo.top())
            self.__stackUndo.pop()
        if self.__stackUndo.is_empty():
            btnUndo['state'] = tk.DISABLED
        else:
            btnUndo['state'] = tk.ACTIVE
        if self.__stackRedo.is_empty():
            btnRedo['state'] = tk.DISABLED
        else:
            btnRedo['state'] = tk.ACTIVE
    def redo(self):
        global btnUndo
        global btnRedo
        if self.__stackRedo.is_empty():
            return
        else:
            entryVar.set(self.__stackRedo.top()['entry'])
            btnDis()
            exec('r'+self.__stackRedo.top()['cmd']+'()')
            btnEna()
            self.__stackUndo.push(self.__stackRedo.top())
            self.__stackRedo.pop()
        if self.__stackUndo.is_empty():
            btnUndo['state'] = tk.DISABLED
        else:
            btnUndo['state'] = tk.ACTIVE
        if self.__stackRedo.is_empty():
            btnRedo['state'] = tk.DISABLED
        else:
            btnRedo['state'] = tk.ACTIVE

record = UndoRedo()

class handler:
    def fd():
        global record
        btnDis()
        p.fd(int(entry1.get()))
        record.clearRedo()
        record.recordUndo('handler.fd',int(entry1.get()))
        btnEna()
    def bk():
        global record
        btnDis()
        p.bk(int(entry1.get()))
        record.clearRedo()
        record.recordUndo('handler.bk',int(entry1.get()))
        btnEna()
    def lt():
        global record
        btnDis()
        p.lt(int(entry1.get()))
        record.clearRedo()
        record.recordUndo('handler.lt',int(entry1.get()))
        btnEna()
    def rt():
        global record
        btnDis()
        p.rt(int(entry1.get()))
        record.clearRedo()
        record.recordUndo('handler.rt',int(entry1.get()))
        btnEna()
    def pdc():
        global pd
        global record
        if pd==True:
            p.penup()
            pd = False
        else:
            p.pendown()
            pd = True
        record.clearRedo()
    def fillc():
        global fill
        global record
        if fill==False:
            p.begin_fill()
            fill = True
        else:
            p.end_fill()
            fill = False
        record.clearRedo()

class rhandler:
    def fd():
        p.fd(int(entry1.get()))
    def bk():
        p.bk(int(entry1.get()))
    def lt():
        p.lt(int(entry1.get()))
    def rt():
        p.rt(int(entry1.get()))

btn1 = tk.Button(window,text='前进',command=handler.fd,font=('Arial', 15))
btn1.grid(row=0,column=1)
btn2 = tk.Button(window,text='后退',command=handler.bk,font=('Arial', 15))
btn2.grid(row=2,column=1)
btn3 = tk.Button(window,text='左转',command=handler.lt,font=('Arial', 15))
btn3.grid(row=1,column=0)
btn4 = tk.Button(window,text='右转',command=handler.rt,font=('Arial', 15))
btn4.grid(row=1,column=2)
btn5 = tk.Button(window,text='抬落',command=handler.pdc,font=('Arial', 15))
btn5.grid(row=0,column=2)
btn6 = tk.Button(window,text='填充',command=handler.fillc,font=('Arial', 15))
btn6.grid(row=2,column=2)

btnUndo = tk.Button(window,text='撤销',command=record.undo,state=tk.DISABLED,font=('Arial', 15))
btnUndo.grid(row=0,column=0)
btnRedo = tk.Button(window,text='重做',command=record.redo,state=tk.DISABLED,font=('Arial', 15))
btnRedo.grid(row=2,column=0)

label = tk.Label(window,text='颜色',font=('Arial', 12))
label.grid(row=0,column=3)
cv = tk.Canvas(window,bg=color,width=45,height=35)
cv.grid(row=1,column=3)
def cc():
    global color
    color = tkcc.askcolor(parent=window,color=color)[1]
    p.color(color,color)
    cv.create_rectangle(0,0,45,35,outline=color,fill=color)
btnSet = tk.Button(window,text='选色',command=cc,font=('Arial', 15))
btnSet.grid(row=2,column=3)

p.fd(0)
window.mainloop()